#include <iostream>
#include <string>
#include <unistd.h>
#include <pthread.h>

#define PTHREAD_NUM 4

typedef void (*func_t)(const std::string& name,pthread_mutex_t* mtx,pthread_cond_t* cond);
volatile bool quit = false;
class ThreadData
{
public:
    ThreadData(const std::string& name,func_t func,pthread_mutex_t* mtx,pthread_cond_t* cond)
        :_name(name),_func(func),_mtx(mtx),_cond(cond)
    {}
    std::string _name;
    func_t _func;
    pthread_mutex_t* _mtx;
    pthread_cond_t* _cond;

};
void func1(const std::string& name,pthread_mutex_t* mtx,pthread_cond_t* cond)
{
    // wait一定要在加锁和解锁之间进行wait！
    while(!quit)
    {
        pthread_mutex_lock(mtx);
         // if(临界资源是否就绪-- 否) pthread_cond_wait
        pthread_cond_wait(cond,mtx);
         if(!quit)std::cout << name << " running -- 播放 " << std::endl;//默认该线程在执行的时候，wait代码被执行，当前线程会被立即被阻塞
        pthread_mutex_unlock(mtx);
        // sleep(1); 
    }
}

void func2(const std::string& name,pthread_mutex_t* mtx,pthread_cond_t* cond)
{
    while(!quit)
    {
        pthread_mutex_lock(mtx);
         // if(临界资源是否就绪-- 否) pthread_cond_wait
        pthread_cond_wait(cond,mtx);
         if(!quit)std::cout << name << " running -- 下载 " << std::endl;//默认该线程在执行的时候，wait代码被执行，当前线程会被立即被阻塞
        pthread_mutex_unlock(mtx);
        // sleep(1); 
    }
}

void func3(const std::string& name,pthread_mutex_t* mtx,pthread_cond_t* cond)
{
    while(!quit)
    {
        pthread_mutex_lock(mtx);
         // if(临界资源是否就绪-- 否) pthread_cond_wait
        pthread_cond_wait(cond,mtx);
         if(!quit)std::cout << name << " running -- 刷新 " << std::endl;//默认该线程在执行的时候，wait代码被执行，当前线程会被立即被阻塞
        pthread_mutex_unlock(mtx);
        sleep(1); 
    }
}

void func4(const std::string& name,pthread_mutex_t* mtx,pthread_cond_t* cond)
{
    while(!quit)
    {
        pthread_mutex_lock(mtx);
         // if(临界资源是否就绪-- 否) pthread_cond_wait
        pthread_cond_wait(cond,mtx);
        if(!quit)std::cout << name << " running -- 扫描用户信息 " << std::endl;//默认该线程在执行的时候，wait代码被执行，当前线程会被立即被阻塞
        pthread_mutex_unlock(mtx);
        // sleep(1); 
    }
}

void* entry(void* args)
{
    ThreadData* td = (ThreadData*)args;
    td->_func(td->_name,td->_mtx,td->_cond);
    delete td;
    return nullptr;
}
int main()
{
    pthread_mutex_t mtx;
    pthread_cond_t cond;
    //初始化锁和条件变量
    pthread_mutex_init(&mtx,nullptr);
    pthread_cond_init(&cond,nullptr);

    pthread_t tids[PTHREAD_NUM];
    func_t func[PTHREAD_NUM] = {func1, func2, func3, func4};

    //创建新线程
    for(int i = 0; i < PTHREAD_NUM; i++)
    {
        std::string name = "THREAD ";
        name += std::to_string(i+1);
        ThreadData* td = new ThreadData(name,func[i],&mtx,&cond);
        pthread_create(tids+i,nullptr,entry,(void*)td);
    }

    sleep(3);

    int cnt = 10;
    while(cnt)
    {
        std::cout << " resume thread run code..." << cnt-- << std::endl;
        pthread_cond_signal(&cond);//按顺序唤醒单个线程
        // pthread_cond_broadcast(&cond);//唤醒全部线程
        sleep(1);
    }

    quit = true;

    pthread_cond_broadcast(&cond);//在唤醒一次执行判断语句

    //等待新线程
    for(int i = 0; i < PTHREAD_NUM; i++)
    {
        pthread_join(tids[i],nullptr);
        std::cout << "thread: " << tids[i] << "quit" << std::endl;
    }

    //释放锁和条件变量
    pthread_mutex_destroy(&mtx);
    pthread_cond_destroy(&cond);


    return 0;
}